import * as vscode from 'vscode'

/**
 * 自动补全提供者类
 * 为4GL语言提供智能代码自动补全功能
 */
export class MyCompletionItemProvider implements vscode.CompletionItemProvider {
    // 缓存结构优化
    private documentIndex = new Map<string, {
        words: Set<string>,
        functions: Map<string, { line: number, params: string[] }>,
        variables: Map<string, { line: number, type: string | null }>,
        lastIndexed: number
    }>()

    // 补全项缓存 - 根据上下文分类
    private completionCache = new Map<string, {
        items: vscode.CompletionItem[],
        timestamp: number
    }>()

    // 上下文模板缓存
    private contextualTemplates: Map<string, vscode.CompletionItem[]> = new Map()

    // 上次文档内容的版本哈希
    private lastDocumentHash = new Map<string, string>()

    // 索引进行中标记（按文档URI粒度）
    private indexingInProgress = new Set<string>()
    // 文档索引防抖定时器
    private debounceTimers = new Map<string, NodeJS.Timeout>()
    // 事件订阅集合，便于释放
    private disposables: vscode.Disposable[] = []

    // 智能补全的最大项目数
    private readonly MAX_COMPLETION_ITEMS = 20

    // 缓存过期时间（毫秒）
    private readonly CACHE_TTL = 30000 // 30秒

    /**
     * 构造函数
     * 初始化自动补全提供者
     */
    constructor() {
        // 初始化上下文模板
        this.initializeContextualTemplates()
        // 初始化基于事件的索引
        this.initIndexingEvents()
    }



    /**
     * 初始化上下文模板
     * 创建常用代码结构的补全模板
     */
    private initializeContextualTemplates() {
        // 函数模板
        this.contextualTemplates.set('function', [
            this.createTemplate(
                'FUNCTION function_name()',
                vscode.CompletionItemKind.Function,
                '函数声明',
                new vscode.SnippetString('FUNCTION ${1:function_name}(${2:parameters})\n\t$0\nEND FUNCTION'),
                '创建一个新的函数声明'
            )
        ])

        // IF语句模板
        this.contextualTemplates.set('if', [
            this.createTemplate(
                'IF condition THEN',
                vscode.CompletionItemKind.Snippet,
                'IF语句',
                new vscode.SnippetString('IF ${1:condition} THEN\n\t$0\nEND IF'),
                '创建一个IF条件语句'
            ),
            this.createTemplate(
                'IF condition THEN ... ELSE',
                vscode.CompletionItemKind.Snippet,
                'IF-ELSE语句',
                new vscode.SnippetString('IF ${1:condition} THEN\n\t$0\nELSE\n\t\nEND IF'),
                '创建一个带ELSE分支的IF语句'
            )
        ])

        // FOR循环模板
        this.contextualTemplates.set('for', [
            this.createTemplate(
                'FOR i = 1 TO n',
                vscode.CompletionItemKind.Snippet,
                'FOR循环',
                new vscode.SnippetString('FOR ${1:i} = ${2:1} TO ${3:n}\n\t$0\nEND FOR'),
                '创建一个FOR循环语句'
            )
        ])

        // SELECT查询模板
        this.contextualTemplates.set('select', [
            this.createTemplate(
                'SELECT fields FROM table',
                vscode.CompletionItemKind.Snippet,
                'SELECT语句',
                new vscode.SnippetString('SELECT ${1:fields}\n  FROM ${2:table}\n WHERE ${3:condition}'),
                '创建一个SELECT查询语句'
            )
        ])

        // 变量定义模板
        this.contextualTemplates.set('define', [
            this.createTemplate(
                'DEFINE variable INTEGER',
                vscode.CompletionItemKind.Snippet,
                '整数变量定义',
                new vscode.SnippetString('DEFINE ${1:variable} INTEGER'),
                '定义一个整数类型变量'
            ),
            this.createTemplate(
                'DEFINE variable STRING',
                vscode.CompletionItemKind.Snippet,
                '字符串变量定义',
                new vscode.SnippetString('DEFINE ${1:variable} STRING'),
                '定义一个字符串类型变量'
            )
        ])
    }

    /**
     * 创建代码模板
     * @param label 模板标签
     * @param kind 模板类型
     * @param detail 模板详情
     * @param insertText 插入文本
     * @param documentation 文档说明
     * @returns 补全项
     */
    private createTemplate(
        label: string,
        kind: vscode.CompletionItemKind,
        detail: string,
        insertText: vscode.SnippetString,
        documentation: string
    ): vscode.CompletionItem {
        const item = new vscode.CompletionItem(label, kind)
        item.insertText = insertText
        item.detail = detail
        item.documentation = new vscode.MarkdownString(documentation)
        item.sortText = 'a' + label // 确保模板排在前面
        return item
    }

    /**
     * 初始化基于事件的索引（带防抖）
     */
    private initIndexingEvents() {
        // 当前活动编辑器文档做一次初始索引
        if (vscode.window.activeTextEditor) {
            this.scheduleIndex(vscode.window.activeTextEditor.document, 0)
        }

        this.disposables.push(
            vscode.workspace.onDidOpenTextDocument(doc => this.scheduleIndex(doc)),
            vscode.workspace.onDidChangeTextDocument(e => this.scheduleIndex(e.document)),
            vscode.workspace.onDidSaveTextDocument(doc => this.scheduleIndex(doc, 50)),
            vscode.workspace.onDidCloseTextDocument(doc => {
                const uri = doc.uri.toString()
                // 清理与该文档相关的缓存和索引
                this.documentIndex.delete(uri)
                this.lastDocumentHash.delete(uri)
                // 清理补全缓存（与上下文相关，简单起见全部清理）
                this.completionCache.clear()
                // 停止进行中的索引标记
                this.indexingInProgress.delete(uri)
                // 清理防抖定时器
                const t = this.debounceTimers.get(uri)
                if (t) {
                    clearTimeout(t)
                    this.debounceTimers.delete(uri)
                }
            }),
            vscode.window.onDidChangeActiveTextEditor(editor => {
                if (editor) this.scheduleIndex(editor.document, 0)
            })
        )
    }

    /**
     * 防抖调度文档索引
     */
    private scheduleIndex(document: vscode.TextDocument, delay = 300) {
        const uri = document.uri.toString()
        const prev = this.debounceTimers.get(uri)
        if (prev) clearTimeout(prev)
        const timer = setTimeout(() => {
            this.indexDocument(document).catch(console.error)
        }, delay)
        this.debounceTimers.set(uri, timer)
    }

    /**
     * 生成文档内容的哈希值
     * @param content 文档内容
     * @returns 哈希值
     */
    private getDocumentHash(content: string): string {
        let hash = 0
        for (let i = 0; i < content.length; i++) {
            const char = content.charCodeAt(i)
            hash = ((hash << 5) - hash) + char
            hash |= 0 // 转换为32位整数
        }
        return hash.toString()
    }

    /**
     * 索引文档内容
     * 提取文档中的标识符、函数和变量用于智能补全
     * @param document VS Code文档对象
     */
    private async indexDocument(document: vscode.TextDocument) {
        const documentText = document.getText()
        const documentUri = document.uri.toString()
        const currentHash = this.getDocumentHash(documentText)

        // 已有进行中的索引则跳过，避免并发
        if (this.indexingInProgress.has(documentUri)) {
            return
        }

        // 如果文档内容没有变化，跳过索引
        if (this.lastDocumentHash.get(documentUri) === currentHash) {
            return
        }

        this.indexingInProgress.add(documentUri)

        // 初始化索引结构
        const words = new Set<string>()
        const functions = new Map<string, { line: number, params: string[] }>()
        const variables = new Map<string, { line: number, type: string | null }>()

        // 分批处理文档行，避免阻塞主线程
        const lines = documentText.split(/\r?\n/)
        const batchSize = 200

        for (let i = 0; i < lines.length; i += batchSize) {
            const batch = lines.slice(i, i + batchSize)

            batch.forEach((line, lineIndex) => {
                const absoluteLineIndex = i + lineIndex

                // 跳过注释行
                if (line.trim().startsWith('#') || line.trim().startsWith('--')) {
                    return
                }

                // 移除字符串内容后再提取标识符
                const codeWithoutStrings = line.replace(/'[^']*'|"[^"]*"/g, '')

                // 提取普通标识符
                const identifierMatches = codeWithoutStrings.match(/[a-zA-Z_][a-zA-Z0-9_]*/g)
                if (identifierMatches) {
                    identifierMatches.forEach(word => {
                        // 过滤掉太短或太长的词，以及纯数字
                        if (word.length >= 2 && word.length <= 30 && !/^\d+$/.test(word)) {
                            words.add(word)
                        }
                    })
                }

                // 识别函数声明
                const functionMatch = codeWithoutStrings.match(/^(private )?function\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\((.*?)\)/i)
                if (functionMatch) {
                    const funcName = functionMatch[2]
                    const params = functionMatch[3].split(',').map(p => p.trim()).filter(p => p.length > 0)
                    functions.set(funcName, { line: absoluteLineIndex, params })
                }

                // 识别变量定义
                const varMatch = codeWithoutStrings.match(/^define\s+([a-zA-Z_][a-zA-Z0-9_]*)\s+([a-zA-Z]+)/i)
                if (varMatch) {
                    const varName = varMatch[1]
                    const varType = varMatch[2]
                    variables.set(varName, { line: absoluteLineIndex, type: varType })
                }
            })

            // 让出主线程
            await new Promise(resolve => setImmediate(resolve))
        }

        // 更新索引和哈希值
        this.documentIndex.set(documentUri, {
            words,
            functions,
            variables,
            lastIndexed: Date.now()
        })

        this.lastDocumentHash.set(documentUri, currentHash)

        // 清除相关缓存，以便下次请求时重新生成补全项
        this.completionCache.clear()

        this.indexingInProgress.delete(documentUri)
    }

    /**
     * 提供补全项函数
     * 根据当前文档内容和上下文提供智能补全建议
     * @param document 当前文档
     * @param position 光标位置
     * @param token 取消令牌
     * @param context 补全上下文
     * @returns 补全项列表
     */
    provideCompletionItems(
        document: vscode.TextDocument,
        position: vscode.Position,
        token: vscode.CancellationToken,
        context: vscode.CompletionContext
    ): vscode.ProviderResult<vscode.CompletionList<vscode.CompletionItem> | vscode.CompletionItem[]> {
        // 获取当前行文本和触发字符
        const lineText = document.lineAt(position).text
        const linePrefix = lineText.substr(0, position.character)

        // 生成缓存键
        const cacheKey = this.generateCacheKey(document, position, linePrefix, context)

        // 检查缓存
        const cached = this.completionCache.get(cacheKey)
        if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
            return cached.items
        }

        // 确保文档已索引
        const documentUri = document.uri.toString()
        if (!this.documentIndex.has(documentUri)) {
            this.indexDocument(document).catch(console.error)
        }

        // 结果集，使用Map确保唯一性
        const resultsMap = new Map<string, vscode.CompletionItem>()

        // 获取当前单词用于过滤
        const wordRange = document.getWordRangeAtPosition(position)
        const currentWord = wordRange ? document.getText(wordRange).toLowerCase() : ''

        // 1. 添加上下文相关的智能补全（优先级最高）
        this.addContextualCompletions(document, position, linePrefix, resultsMap, currentWord)

        // 2. 添加函数补全（优先级次之）
        this.addFunctionCompletions(document, resultsMap, currentWord)

        // 3. 添加变量补全
        this.addVariableCompletions(document, resultsMap, currentWord)

        // 4. 关键字补全已由服务器端提供，客户端不再重复提供

        // 5. 添加文档中的其他标识符补全
        this.addDocumentIdentifierCompletions(document, position, resultsMap, currentWord)

        // 转换为数组并限制数量
        const results = Array.from(resultsMap.values()).slice(0, this.MAX_COMPLETION_ITEMS)

        // 缓存结果
        this.completionCache.set(cacheKey, {
            items: results,
            timestamp: Date.now()
        })

        return results
    }

    /**
     * 生成缓存键
     * @param document 当前文档
     * @param position 光标位置
     * @param linePrefix 行前缀
     * @param context 补全上下文
     * @returns 唯一的缓存键
     */
    private generateCacheKey(
        document: vscode.TextDocument,
        position: vscode.Position,
        linePrefix: string,
        context: vscode.CompletionContext
    ): string {
        // 获取前几行的内容作为上下文
        const startLine = Math.max(0, position.line - 3)
        const contextRange = new vscode.Range(startLine, 0, position.line, position.character)
        const contextText = document.getText(contextRange)

        // 获取触发字符
        const triggerCharacter = context.triggerCharacter || ''

        // 引入文档URI与版本、行号，降低不同文档/位置间的碰撞
        const meta = `${document.uri.toString()}|v${document.version}|l${position.line}`

        // 生成哈希
        const contentToHash = meta + '|' + contextText + '|' + triggerCharacter
        return this.getDocumentHash(contentToHash)
    }



    /**
     * 获取最后一个单词
     * @param text 文本
     * @returns 最后一个单词
     */
    private getLastWord(text: string): string {
        const words = text.split(/\s+/).filter(word => word.length > 0)
        return words.length > 0 ? words[words.length - 1].toLowerCase() : ''
    }

    /**
     * 添加上下文相关的补全项
     * @param document 当前文档
     * @param position 光标位置
     * @param linePrefix 行前缀
     * @param resultsMap 结果映射
     * @param currentWord 当前输入的单词
     */
    private addContextualCompletions(
        document: vscode.TextDocument,
        position: vscode.Position,
        linePrefix: string,
        resultsMap: Map<string, vscode.CompletionItem>,
        currentWord: string
    ) {
        const trimmedPrefix = linePrefix.trim().toLowerCase()
        const lastWord = this.getLastWord(trimmedPrefix)

        // 根据最后一个单词获取对应的模板
        const templateKey = this.getContextTemplateKey(lastWord)
        if (templateKey && this.contextualTemplates.has(templateKey)) {
            const templates = this.contextualTemplates.get(templateKey)!

            templates.forEach(template => {
                // 过滤与当前输入匹配的模板
                if (template.label.toString().toLowerCase().includes(currentWord)) {
                    resultsMap.set(template.label.toString(), template)
                }
            })
        }

        // 函数调用补全 - 检查是否在函数调用的参数列表中
        this.addFunctionParameterCompletions(document, position, linePrefix, resultsMap, currentWord)
    }

    /**
     * 获取上下文模板键
     * @param lastWord 最后一个单词
     * @returns 模板键
     */
    private getContextTemplateKey(lastWord: string): string | null {
        const templateKeys: { [key: string]: string } = {
            'function': 'function',
            'if': 'if',
            'for': 'for',
            'select': 'select',
            'define': 'define'
        }

        return templateKeys[lastWord] || null
    }

    /**
     * 添加函数参数补全
     * @param document 当前文档
     * @param position 光标位置
     * @param linePrefix 行前缀
     * @param resultsMap 结果映射
     * @param currentWord 当前输入的单词
     */
    private addFunctionParameterCompletions(
        document: vscode.TextDocument,
        position: vscode.Position,
        linePrefix: string,
        resultsMap: Map<string, vscode.CompletionItem>,
        currentWord: string
    ) {
        // 检查是否在函数调用的参数列表中
        const functionCallMatch = linePrefix.match(/([a-zA-Z_][a-zA-Z0-9_]*)\s*\($/)
        if (functionCallMatch) {
            const functionName = functionCallMatch[1]
            const documentUri = document.uri.toString()
            const index = this.documentIndex.get(documentUri)

            if (index && index.functions.has(functionName)) {
                const funcInfo = index.functions.get(functionName)!

                // 为每个参数创建补全项
                funcInfo.params.forEach((param, i) => {
                    if (param.toLowerCase().includes(currentWord)) {
                        const item = new vscode.CompletionItem(
                            param,
                            vscode.CompletionItemKind.Variable
                        )
                        item.detail = `参数 ${i + 1}`
                        item.documentation = new vscode.MarkdownString(`函数 \`${functionName}\` 的参数`)
                        item.sortText = `aa${param}` // 确保参数排在最前面
                        resultsMap.set(param, item)
                    }
                })
            }
        }
    }

    /**
     * 添加函数补全项
     * @param document 当前文档
     * @param resultsMap 结果映射
     * @param currentWord 当前输入的单词
     */
    private addFunctionCompletions(
        document: vscode.TextDocument,
        resultsMap: Map<string, vscode.CompletionItem>,
        currentWord: string
    ) {
        const documentUri = document.uri.toString()
        const index = this.documentIndex.get(documentUri)

        if (!index) {
            return
        }

        // 遍历索引中的函数
        index.functions.forEach((info, funcName) => {
            // 过滤与当前输入匹配的函数
            if (!funcName.toLowerCase().includes(currentWord)) {
                return
            }

            const item = new vscode.CompletionItem(
                funcName,
                vscode.CompletionItemKind.Function
            )

            // 添加函数签名信息
            const paramsStr = info.params.join(', ')
            item.detail = `函数 (${paramsStr})`

            // 添加文档说明
            const doc = new vscode.MarkdownString()
            doc.appendMarkdown(`**${funcName}(${paramsStr})**\n\n`)
            doc.appendMarkdown(`定义在第 ${info.line + 1} 行\n\n`)
            doc.appendMarkdown(`**用法示例:**\n`)
            doc.appendCodeblock(`${funcName}(${info.params.map((_, i) => `param${i + 1}`).join(', ')})`, '4gl')

            item.documentation = doc

            // 设置排序文本，确保函数排在前面
            item.sortText = 'b' + funcName

            // 添加补全项
            resultsMap.set(funcName, item)
        })
    }

    /**
     * 添加变量补全项
     * @param document 当前文档
     * @param resultsMap 结果映射
     * @param currentWord 当前输入的单词
     */
    private addVariableCompletions(
        document: vscode.TextDocument,
        resultsMap: Map<string, vscode.CompletionItem>,
        currentWord: string
    ) {
        const documentUri = document.uri.toString()
        const index = this.documentIndex.get(documentUri)

        if (!index) {
            return
        }

        // 遍历索引中的变量
        index.variables.forEach((info, varName) => {
            // 过滤与当前输入匹配的变量
            if (!varName.toLowerCase().includes(currentWord)) {
                return
            }

            const item = new vscode.CompletionItem(
                varName,
                vscode.CompletionItemKind.Variable
            )

            // 添加变量类型信息
            item.detail = info.type ? `${info.type} 变量` : '变量'

            // 添加文档说明
            const doc = new vscode.MarkdownString()
            doc.appendMarkdown(`**${varName}**\n\n`)
            if (info.type) {
                doc.appendMarkdown(`类型: ${info.type}\n\n`)
            }
            doc.appendMarkdown(`定义在第 ${info.line + 1} 行`)

            item.documentation = doc

            // 设置排序文本
            item.sortText = 'c' + varName

            // 添加补全项
            resultsMap.set(varName, item)
        })
    }



    /**
     * 添加文档中的其他标识符补全
     * @param document 当前文档
     * @param position 光标位置
     * @param resultsMap 结果映射
     * @param currentWord 当前输入的单词
     */
    private addDocumentIdentifierCompletions(
        document: vscode.TextDocument,
        position: vscode.Position,
        resultsMap: Map<string, vscode.CompletionItem>,
        currentWord: string
    ) {
        const documentUri = document.uri.toString()
        const index = this.documentIndex.get(documentUri)

        if (!index) {
            return
        }

        // 遍历索引中的单词，但排除已经添加的函数和变量
        index.words.forEach(word => {
            // 跳过已存在于结果中的项
            if (resultsMap.has(word)) {
                return
            }

            // 跳过函数和变量（已经单独添加）
            if (index.functions.has(word) || index.variables.has(word)) {
                return
            }

            // 过滤与当前输入匹配的标识符
            if (!word.toLowerCase().includes(currentWord)) {
                return
            }

            const item = new vscode.CompletionItem(
                word,
                this.guessCompletionItemKind(word)
            )

            // 添加基本文档说明
            item.documentation = new vscode.MarkdownString(`**${word}**\n\n文档中的标识符`)

            // 设置排序文本
            item.sortText = 'd' + word

            // 添加补全项
            resultsMap.set(word, item)
        })
    }

    /**
     * 猜测补全项类型
     * @param word 标识符
     * @returns 补全项类型
     */
    private guessCompletionItemKind(word: string): vscode.CompletionItemKind {
        // 如果以()结尾，认为是函数（但实际上我们已经单独处理了函数）
        if (word.endsWith('()')) {
            return vscode.CompletionItemKind.Function
        }

        // 如果包含下划线或全部大写，可能是常量
        if (word.includes('_') || word === word.toUpperCase()) {
            return vscode.CompletionItemKind.Constant
        }

        // 默认为变量
        return vscode.CompletionItemKind.Variable
    }

    /**
     * 解析补全项函数
     * 当用户选中补全项时调用
     * @param item 补全项
     * @param token 取消令牌
     * @returns 补全项或Promise
     */
    resolveCompletionItem(
        item: vscode.CompletionItem,
        token: vscode.CancellationToken
    ): vscode.ProviderResult<vscode.CompletionItem> {
        // 可以在这里添加更多的补全项解析逻辑
        return item
    }

    /**
     * 释放资源
     */
    public dispose() {
        this.disposables.forEach(d => {
            try { d.dispose() } catch { /* noop */ }
        })
        this.disposables = []
        // 清理所有定时器
        this.debounceTimers.forEach(t => {
            try { clearTimeout(t) } catch { /* noop */ }
        })
        this.debounceTimers.clear()
        this.indexingInProgress.clear()
    }
}

/**
 * 代码操作提供者类
 * 为4GL语言提供代码操作建议（如快速修复）
 */
/**
 * 跳转定义提供者
 * - 支持 function 名与 define 变量的定义位置跳转
 */
export class MyDefinitionProvider implements vscode.DefinitionProvider {
    provideDefinition(
        document: vscode.TextDocument,
        position: vscode.Position,
        token: vscode.CancellationToken
    ): vscode.ProviderResult<vscode.Definition | vscode.DefinitionLink[]> {
        const wordRange = document.getWordRangeAtPosition(position, /[A-Za-z_][A-Za-z0-9_]*/)
        if (!wordRange) return undefined
        const name = document.getText(wordRange)
        const nameLower = name.toLowerCase()

        const text = document.getText()
        const lines = text.split(/\r?\n/)

        // 扫描定义行：function 与 define（忽略注释前缀）
        for (let i = 0; i < lines.length; i++) {
            const raw = lines[i]
            const code = raw.split('#')[0].split('--')[0] ?? ''
            const lower = code.toLowerCase()

            // function 定义：可含 private
            // 例如：FUNCTION foo(a,b) 或 private function foo(...)
            const fnPattern = new RegExp(`^\\s*(?:private\\s+)?function\\s+${escapeRegExp(nameLower)}\\b`, 'i')
            if (fnPattern.test(code)) {
                const col = Math.max(0, lower.indexOf(nameLower))
                return new vscode.Location(document.uri, new vscode.Position(i, col))
            }

            // 变量定义：DEFINE var TYPE
            const defVarPattern = new RegExp(`^\\s*define\\s+${escapeRegExp(nameLower)}\\b`, 'i')
            if (defVarPattern.test(code)) {
                const col = Math.max(0, lower.indexOf(nameLower))
                return new vscode.Location(document.uri, new vscode.Position(i, col))
            }

            // PREPARE 定义：PREPARE name FROM ...
            const preparePattern = new RegExp(`^\\s*prepare\\s+${escapeRegExp(nameLower)}\\b`, 'i')
            if (preparePattern.test(code)) {
                const col = Math.max(0, lower.indexOf(nameLower))
                return new vscode.Location(document.uri, new vscode.Position(i, col))
            }

            // DECLARE 定义：DECLARE name CURSOR FOR ...
            const declarePattern = new RegExp(`^\\s*declare\\s+${escapeRegExp(nameLower)}\\b`, 'i')
            if (declarePattern.test(code)) {
                const col = Math.max(0, lower.indexOf(nameLower))
                return new vscode.Location(document.uri, new vscode.Position(i, col))
            }
        }
        return undefined
    }
}

/**
 * 查找引用提供者
 * - 在当前文档内按词边界查找匹配
 * - context.includeDeclaration 控制是否包含定义处
 */
export class MyReferenceProvider implements vscode.ReferenceProvider {
    provideReferences(
        document: vscode.TextDocument,
        position: vscode.Position,
        context: { includeDeclaration: boolean },
        token: vscode.CancellationToken
    ): vscode.ProviderResult<vscode.Location[]> {
        const wordRange = document.getWordRangeAtPosition(position, /[A-Za-z_][A-Za-z0-9_]*/)
        if (!wordRange) return []
        const name = document.getText(wordRange)
        const nameLower = name.toLowerCase()

        const text = document.getText()
        const lines = text.split(/\r?\n/)
        const wordRegex = new RegExp(`\\b${escapeRegExp(name)}\\b`, 'g')

        const locations: vscode.Location[] = []
        for (let i = 0; i < lines.length; i++) {
            const raw = lines[i]
            // 简单剥离注释后再搜索，降低误报
            const code = raw.split('#')[0].split('--')[0] ?? ''
            let m: RegExpExecArray | null
            wordRegex.lastIndex = 0
            while ((m = wordRegex.exec(code)) !== null) {
                const col = m.index
                // 如果不包含定义，需要排除定义行
                if (!context.includeDeclaration) {
                    const lower = code.toLowerCase()
                    const isFnDef = new RegExp(`^\\s*(?:private\\s+)?function\\s+${escapeRegExp(nameLower)}\\b`, 'i').test(code)
                    const isVarDef = new RegExp(`^\\s*define\\s+${escapeRegExp(nameLower)}\\b`, 'i').test(code)
                    const isPrepareDef = new RegExp(`^\\s*prepare\\s+${escapeRegExp(nameLower)}\\b`, 'i').test(code)
                    const isDeclareDef = new RegExp(`^\\s*declare\\s+${escapeRegExp(nameLower)}\\b`, 'i').test(code)
                    if (isFnDef || isVarDef || isPrepareDef || isDeclareDef) continue
                }
                locations.push(new vscode.Location(document.uri, new vscode.Position(i, col)))
            }
        }
        return locations
    }
}

/** 工具：转义正则特殊字符 */
function escapeRegExp(s: string): string {
    return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}

export class MyCodeActionProvider implements vscode.CodeActionProvider {
    /**
     * 提供代码操作函数
     * 根据诊断信息提供代码修复建议
     * @param document 当前文档
     * @param range 选择范围
     * @param context 代码操作上下文
     * @param token 取消令牌
     * @returns 代码操作数组
     */
    provideCodeActions(
        document: vscode.TextDocument,
        range: vscode.Range | vscode.Selection,
        context: vscode.CodeActionContext,
        token: vscode.CancellationToken
    ): vscode.ProviderResult<(vscode.CodeAction | vscode.Command)[]> {
        const fixes: vscode.CodeAction[] = []

        // 1) 基于诊断信息的自动修复
        for (const d of context.diagnostics ?? []) {
            const msg = d.message || ''
            const dRange = new vscode.Range(
                d.range.start.line, d.range.start.character,
                d.range.end.line, d.range.end.character
            )

            // 关键字需要大写
            if (msg.includes('关键字需要大写')) {
                const text = document.getText(dRange)
                if (text && text !== text.toUpperCase()) {
                    const fix = new vscode.CodeAction('将关键字改为大写', vscode.CodeActionKind.QuickFix)
                    fix.diagnostics = [d]
                    fix.edit = new vscode.WorkspaceEdit()
                    fix.edit.replace(document.uri, dRange, text.toUpperCase())
                    fixes.push(fix)
                }
                continue
            }

            // IF 缺少 THEN：在 IF 行末添加 THEN（仅当该行不含 THEN）
            if (msg.includes('IF 缺少 THEN')) {
                const line = d.range.start.line
                const lineText = document.lineAt(line).text
                if (!/\bTHEN\b/i.test(lineText)) {
                    const fix = new vscode.CodeAction('在该 IF 行末添加 THEN', vscode.CodeActionKind.QuickFix)
                    fix.diagnostics = [d]
                    fix.edit = new vscode.WorkspaceEdit()
                    fix.edit.insert(document.uri, new vscode.Position(line, lineText.length), ' THEN')
                    fixes.push(fix)
                }
                continue
            }

            // DECLARE 结构：允许 FOR/FROM；若缺失则在 CURSOR 后插入 " FOR "
            if (msg.includes('DECLARE 语句应为')) {
                const line = d.range.start.line
                const lineText = document.lineAt(line).text
                const hasFor = /\bCURSOR\s+FOR\b/i.test(lineText)
                const hasFrom = /\bCURSOR\s+FROM\b/i.test(lineText)
                const cursorIdx = lineText.toUpperCase().indexOf('CURSOR')
                if (cursorIdx >= 0 && !hasFor && !hasFrom) {
                    const insertPos = cursorIdx + 'CURSOR'.length
                    const fix = new vscode.CodeAction('在 CURSOR 后插入 " FOR "', vscode.CodeActionKind.QuickFix)
                    fix.diagnostics = [d]
                    fix.edit = new vscode.WorkspaceEdit()
                    fix.edit.insert(document.uri, new vscode.Position(line, insertPos), ' FOR')
                    fixes.push(fix)
                }
                continue
            }

            // PREPARE 结构：若缺 FROM 则在行末补 " FROM "
            if (msg.includes('PREPARE 语句应为')) {
                const line = d.range.start.line
                const lineText = document.lineAt(line).text
                if (!/\bFROM\b/i.test(lineText)) {
                    const fix = new vscode.CodeAction('在该 PREPARE 行末添加 " FROM "', vscode.CodeActionKind.QuickFix)
                    fix.diagnostics = [d]
                    fix.edit = new vscode.WorkspaceEdit()
                    fix.edit.insert(document.uri, new vscode.Position(line, lineText.length), ' FROM ')
                    fixes.push(fix)
                }
                continue
            }
        }

        if (fixes.length > 0) {
            return fixes
        }

        // 2) 兜底：保持原有“将单词转为大写”的手动修复（基于光标词）
        const pos = range.start
        const wordRange = document.getWordRangeAtPosition(pos, /\w+/)
        if (!wordRange) return []

        const word = document.getText(wordRange)
        if (!word) return []

        const newWord = word.toUpperCase()
        if (newWord === word) return []

        const manual = new vscode.CodeAction('将单词转为大写', vscode.CodeActionKind.QuickFix)
        manual.edit = new vscode.WorkspaceEdit()
        manual.edit.replace(document.uri, wordRange, newWord)

        return [manual]
    }

    /**
     * 解析代码操作函数
     * 当用户选中代码操作时调用
     * @param codeAction 代码操作
     * @param token 取消令牌
     * @returns 代码操作或Promise
     */
    resolveCodeAction?(
        codeAction: vscode.CodeAction,
        token: vscode.CancellationToken
    ): vscode.ProviderResult<vscode.CodeAction> {
        return codeAction
    }
}